const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');

const execAsync = promisify(exec);

class CompatibilityTester {
  constructor() {
    this.results = [];
    this.testDir = path.join(__dirname, '../tests');
    this.reportsDir = path.join(__dirname, '../test-results');
    this.startTime = Date.now();
  }

  async runAllTests() {
    console.log('🚀 开始AI Agent平台兼容性测试...');
    console.log(`📅 测试时间: ${new Date().toISOString()}`);
    console.log(`📁 测试目录: ${this.testDir}`);

    try {
      // 阶段1: 环境检查
      await this.checkEnvironment();

      // 阶段2: 依赖检查
      await this.checkDependencies();

      // 阶段3: 配置检查
      await this.checkConfigurations();

      // 阶段4: 基础E2E测试
      await this.runBasicE2ETests();

      // 阶段5: 功能测试
      await this.runFunctionalTests();

      // 阶段6: 性能测试
      await this.runPerformanceTests();

      // 阶段7: 跨浏览器测试
      await this.runCrossBrowserTests();

      // 阶段8: 生成报告
      await this.generateReport();

      const duration = Date.now() - this.startTime;
      console.log(`✅ 兼容性测试完成，总耗时: ${this.formatDuration(duration)}`);

    } catch (error) {
      console.error('❌ 兼容性测试失败:', error);
      this.results.push({
        test: '兼容性测试总体',
        status: 'FAIL',
        error: error.message
      });
      await this.generateReport();
    }
  }

  async checkEnvironment() {
    console.log('\n🔍 阶段1: 环境检查...');

    const checks = [
      {
        name: 'Node.js版本',
        command: 'node --version',
        validator: (output) => {
          const version = parseFloat(output.match(/v(\d+\.\d+)/)?.[1] || '0');
          return version >= 18.0;
        },
        description: 'Node.js版本 >= 18.0'
      },
      {
        name: 'npm版本',
        command: 'npm --version',
        validator: (output) => {
          const version = parseFloat(output);
          return version >= 8.0;
        },
        description: 'npm版本 >= 8.0'
      },
      {
        name: 'TypeScript版本',
        command: 'npx tsc --version',
        validator: (output) => {
          const version = parseFloat(output.match(/Version (\d+\.\d+)/)?.[1] || '0');
          return version >= 4.9;
        },
        description: 'TypeScript版本 >= 4.9'
      },
      {
        name: 'CRACO配置',
        command: 'ls node_modules/.bin/craco',
        validator: () => true,
        description: 'CRACO可用'
      },
      {
        name: 'Playwright安装',
        command: 'npx playwright --version',
        validator: () => true,
        description: 'Playwright已安装'
      }
    ];

    for (const check of checks) {
      try {
        console.log(`  📋 检查: ${check.name}`);
        const { stdout } = await execAsync(check.command);
        const isValid = check.validator(stdout);

        if (isValid) {
          console.log(`    ✅ ${check.name}: 通过`);
          this.results.push({
            test: check.name,
            status: 'PASS',
            description: check.description,
            details: stdout.trim()
          });
        } else {
          console.log(`    ❌ ${check.name}: 失败`);
          this.results.push({
            test: check.name,
            status: 'FAIL',
            description: check.description,
            details: stdout.trim()
          });
        }
      } catch (error) {
        console.log(`    ❌ ${check.name}: 错误 - ${error.message}`);
        this.results.push({
          test: check.name,
          status: 'FAIL',
          description: check.description,
          error: error.message
        });
      }
    }
  }

  async checkDependencies() {
    console.log('\n📦 阶段2: 依赖检查...');

    const packageJsonPath = path.join(__dirname, '../package.json');
    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));

    const requiredDeps = [
      'react',
      'react-dom',
      'antd',
      'axios',
      'react-router-dom',
      'typescript',
      '@types/react',
      '@types/node'
    ];

    const requiredDevDeps = [
      '@playwright/test',
      '@craco/craco',
      '@testing-library/jest-dom',
      '@testing-library/react',
      'eslint',
      'prettier'
    ];

    // 检查生产依赖
    for (const dep of requiredDeps) {
      const version = packageJson.dependencies?.[dep];
      if (version) {
        console.log(`    ✅ 生产依赖: ${dep}@${version}`);
        this.results.push({
          test: `生产依赖: ${dep}`,
          status: 'PASS',
          details: version
        });
      } else {
        console.log(`    ❌ 缺少生产依赖: ${dep}`);
        this.results.push({
          test: `生产依赖: ${dep}`,
          status: 'FAIL',
          error: '依赖不存在'
        });
      }
    }

    // 检查开发依赖
    for (const dep of requiredDevDeps) {
      const version = packageJson.devDependencies?.[dep];
      if (version) {
        console.log(`    ✅ 开发依赖: ${dep}@${version}`);
        this.results.push({
          test: `开发依赖: ${dep}`,
          status: 'PASS',
          details: version
        });
      } else {
        console.log(`    ❌ 缺少开发依赖: ${dep}`);
        this.results.push({
          test: `开发依赖: ${dep}`,
          status: 'FAIL',
          error: '依赖不存在'
        });
      }
    }
  }

  async checkConfigurations() {
    console.log('\n⚙️ 阶段3: 配置检查...');

    const configFiles = [
      {
        path: 'playwright.config.ts',
        description: 'Playwright配置文件'
      },
      {
        path: 'craco.config.js',
        description: 'CRACO配置文件'
      },
      {
        path: 'tsconfig.json',
        description: 'TypeScript配置文件'
      },
      {
        path: '.env.test',
        description: '测试环境变量'
      },
      {
        path: 'tests/global-setup.ts',
        description: '全局设置'
      },
      {
        path: 'tests/global-teardown.ts',
        description: '全局清理'
      }
    ];

    for (const config of configFiles) {
      const fullPath = path.join(__dirname, '..', config.path);
      if (fs.existsSync(fullPath)) {
        console.log(`    ✅ 配置文件: ${config.description}`);
        this.results.push({
          test: config.description,
          status: 'PASS',
          details: `文件存在: ${config.path}`
        });
      } else {
        console.log(`    ❌ 缺少配置: ${config.description}`);
        this.results.push({
          test: config.description,
          status: 'FAIL',
          error: `文件不存在: ${config.path}`
        });
      }
    }
  }

  async runBasicE2ETests() {
    console.log('\n🧪 阶段4: 基础E2E测试...');

    const basicTests = [
      {
        name: '页面加载测试',
        command: 'npx playwright test tests/e2e/auth/auth.spec.ts --grep "TC-001" --reporter=list',
        description: '页面基础加载功能'
      },
      {
        name: '用户认证测试',
        command: 'npx playwright test tests/e2e/auth/auth.spec.ts --grep "TC-005" --reporter=list',
        description: '用户登录登出功能'
      }
    ];

    for (const test of basicTests) {
      try {
        console.log(`  🧪 运行: ${test.name}`);
        const { stdout, stderr } = await execAsync(test.command, {
          cwd: path.join(__dirname, '..'),
          timeout: 60000
        });

        if (stderr.includes('failed') || stderr.includes('error')) {
          throw new Error(stderr);
        }

        console.log(`    ✅ ${test.name}: 通过`);
        this.results.push({
          test: test.name,
          status: 'PASS',
          description: test.description,
          details: stdout
        });
      } catch (error) {
        console.log(`    ❌ ${test.name}: 失败`);
        this.results.push({
          test: test.name,
          status: 'FAIL',
          description: test.description,
          error: error.message
        });
      }
    }
  }

  async runFunctionalTests() {
    console.log('\n🔧 阶段5: 功能测试...');

    const functionalTests = [
      {
        name: 'Agent管理功能',
        command: 'npx playwright test tests/e2e/agents/agent-management.spec.ts --grep "TC-101" --reporter=list',
        description: 'Agent基础管理功能'
      },
      {
        name: '对话功能',
        command: 'npx playwright test tests/e2e/conversations/conversation.spec.ts --grep "TC-201" --reporter=list',
        description: '对话基础功能'
      }
    ];

    for (const test of functionalTests) {
      try {
        console.log(`  🧪 运行: ${test.name}`);
        const { stdout, stderr } = await execAsync(test.command, {
          cwd: path.join(__dirname, '..'),
          timeout: 90000
        });

        if (stderr.includes('failed') || stderr.includes('error')) {
          throw new Error(stderr);
        }

        console.log(`    ✅ ${test.name}: 通过`);
        this.results.push({
          test: test.name,
          status: 'PASS',
          description: test.description,
          details: stdout
        });
      } catch (error) {
        console.log(`    ❌ ${test.name}: 失败`);
        this.results.push({
          test: test.name,
          status: 'FAIL',
          description: test.description,
          error: error.message
        });
      }
    }
  }

  async runPerformanceTests() {
    console.log('\n⚡ 阶段6: 性能测试...');

    const performanceTests = [
      {
        name: '登录响应时间',
        command: 'npx playwright test tests/e2e/auth/auth.spec.ts --grep "TC-009" --reporter=list',
        description: '用户登录性能测试'
      },
      {
        name: 'Agent加载性能',
        command: 'npx playwright test tests/e2e/agents/agent-management.spec.ts --grep "TC-113" --reporter=list',
        description: 'Agent列表加载性能'
      }
    ];

    for (const test of performanceTests) {
      try {
        console.log(`  🧪 运行: ${test.name}`);
        const { stdout, stderr } = await execAsync(test.command, {
          cwd: path.join(__dirname, '..'),
          timeout: 120000
        });

        console.log(`    ✅ ${test.name}: 完成`);
        this.results.push({
          test: test.name,
          status: 'PASS',
          description: test.description,
          details: stdout
        });
      } catch (error) {
        console.log(`    ❌ ${test.name}: 失败`);
        this.results.push({
          test: test.name,
          status: 'FAIL',
          description: test.description,
          error: error.message
        });
      }
    }
  }

  async runCrossBrowserTests() {
    console.log('\n🌐 阶段7: 跨浏览器测试...');

    const browserTests = [
      {
        name: 'Chrome测试',
        command: 'npx playwright test tests/e2e/auth/auth.spec.ts --grep "TC-001" --project=chromium --reporter=list',
        description: 'Chrome浏览器兼容性'
      },
      {
        name: 'Firefox测试',
        command: 'npx playwright test tests/e2e/auth/auth.spec.ts --grep "TC-001" --project=firefox --reporter=list',
        description: 'Firefox浏览器兼容性'
      }
    ];

    for (const test of browserTests) {
      try {
        console.log(`  🧪 运行: ${test.name}`);
        const { stdout, stderr } = await execAsync(test.command, {
          cwd: path.join(__dirname, '..'),
          timeout: 90000
        });

        console.log(`    ✅ ${test.name}: 通过`);
        this.results.push({
          test: test.name,
          status: 'PASS',
          description: test.description,
          details: stdout
        });
      } catch (error) {
        console.log(`    ❌ ${test.name}: 失败`);
        this.results.push({
          test: test.name,
          status: 'FAIL',
          description: test.description,
          error: error.message
        });
      }
    }
  }

  async generateReport() {
    console.log('\n📊 阶段8: 生成兼容性测试报告...');

    const summary = {
      testDate: new Date().toISOString(),
      duration: this.formatDuration(Date.now() - this.startTime),
      environment: process.platform,
      nodeVersion: process.version,
      total: this.results.length,
      passed: this.results.filter(r => r.status === 'PASS').length,
      failed: this.results.filter(r => r.status === 'FAIL').length,
      passRate: Math.round((this.results.filter(r => r.status === 'PASS').length / this.results.length) * 100),
      results: this.results
    };

    // 确保报告目录存在
    if (!fs.existsSync(this.reportsDir)) {
      fs.mkdirSync(this.reportsDir, { recursive: true });
    }

    // 生成JSON报告
    const jsonReportPath = path.join(this.reportsDir, 'compatibility-report.json');
    fs.writeFileSync(jsonReportPath, JSON.stringify(summary, null, 2));

    // 生成Markdown报告
    const markdownReport = this.generateMarkdownReport(summary);
    const markdownPath = path.join(this.reportsDir, 'compatibility-report.md');
    fs.writeFileSync(markdownPath, markdownReport);

    // 显示摘要
    console.log('\n📋 兼容性测试摘要:');
    console.log(`   总测试数: ${summary.total}`);
    console.log(`   通过数: ${summary.passed}`);
    console.log(`   失败数: ${summary.failed}`);
    console.log(`   通过率: ${summary.passRate}%`);
    console.log(`   测试耗时: ${summary.duration}`);
    console.log(`\n📄 详细报告:`);
    console.log(`   JSON报告: ${jsonReportPath}`);
    console.log(`   Markdown报告: ${markdownPath}`);

    // 如果有失败的测试，显示详细信息
    if (summary.failed > 0) {
      console.log('\n❌ 失败的测试:');
      this.results
        .filter(r => r.status === 'FAIL')
        .forEach(result => {
          console.log(`   - ${result.test}: ${result.error || result.details}`);
        });
    }
  }

  generateMarkdownReport(summary) {
    return `# AI Agent平台兼容性测试报告

## 测试概览
- **测试时间**: ${summary.testDate}
- **测试耗时**: ${summary.duration}
- **运行环境**: ${summary.environment}
- **Node.js版本**: ${summary.nodeVersion}

## 测试结果摘要
- **总测试数**: ${summary.total}
- **通过数**: ${summary.passed}
- **失败数**: ${summary.failed}
- **通过率**: ${summary.passRate}%

## 详细测试结果

### ✅ 通过的测试 (${summary.passed})
${summary.results
  .filter(r => r.status === 'PASS')
  .map(r => `- **${r.test}**: ${r.description || '通过'}`)
  .join('\n')}

### ❌ 失败的测试 (${summary.failed})
${summary.results
  .filter(r => r.status === 'FAIL')
  .map(r => `- **${r.test}**: ${r.error || r.details}`)
  .join('\n')}

## 建议
${summary.failed > 0 ?
  `发现 ${summary.failed} 个问题，建议修复失败的项目后再进行生产部署。` :
  '所有兼容性测试均通过，项目适合进行生产部署。'}

---
*报告生成时间: ${new Date().toLocaleString('zh-CN')}*
`;
  }

  formatDuration(ms) {
    const seconds = Math.floor(ms / 1000);
    const minutes = Math.floor(seconds / 60);
    const hours = Math.floor(minutes / 60);

    if (hours > 0) {
      return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
    } else if (minutes > 0) {
      return `${minutes}m ${seconds % 60}s`;
    } else {
      return `${seconds}s`;
    }
  }
}

// 运行兼容性测试
const tester = new CompatibilityTester();
tester.runAllTests().catch(error => {
  console.error('兼容性测试执行失败:', error);
  process.exit(1);
});